package phoeics.authoryserver.webservice.service.impl;

import java.util.List;
import java.util.concurrent.TimeUnit;

import javax.annotation.PostConstruct;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataAccessException;
import org.springframework.data.redis.connection.RedisConnection;
import org.springframework.data.redis.core.RedisCallback;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.stereotype.Service;

import phoeics.authoryserver.util.JacksonUtil;
import phoeics.authoryserver.webservice.service.RedisService;

@Service 
public class RedisServiceImpl implements RedisService{
	//private static org.slf4j.Logger logger = org.slf4j.LoggerFactory.getLogger(RedisServiceImpl.class);
	@Autowired  
    private RedisTemplate<String, ?> redisTemplate;  
	private RedisSerializer<String> serializer = null;
	@PostConstruct  
    public void initMethod()  {  
		 this.serializer = redisTemplate.getStringSerializer();
    }  
    @Override  
    public boolean set(final String key, final String value) {  
        boolean result = redisTemplate.execute(new RedisCallback<Boolean>() {  
            @Override  
            public Boolean doInRedis(RedisConnection connection) throws DataAccessException {  
                connection.set(serializer.serialize(key), serializer.serialize(value));  
                return true;  
            }  
        });  
        return result;  
    }  
    @Override  
    public <T> boolean set(final String key, final T value) {  
        boolean result = redisTemplate.execute(new RedisCallback<Boolean>() {  
            @Override  
            public Boolean doInRedis(RedisConnection connection) throws DataAccessException {  
                connection.set(serializer.serialize(key), serializer.serialize( JacksonUtil.toJSon(value)));  
                return true;  
            }  
        });  
        return result;  
    }  
    @Override 
    public String get(final String key){  
        String result = redisTemplate.execute(new RedisCallback<String>() {  
            @Override  
            public String doInRedis(RedisConnection connection) throws DataAccessException {  
                byte[] value =  connection.get(serializer.serialize(key));  
                return serializer.deserialize(value);  
            }  
        });  
        return result;  
    }  
    
    @Override 
    public <T> T get(final String key,Class<T> valueType){  
        String result = redisTemplate.execute(new RedisCallback<String>() {  
            @Override  
            public String doInRedis(RedisConnection connection) throws DataAccessException {  
                byte[] value =  connection.get(serializer.serialize(key));  
                return serializer.deserialize(value);  
            }  
        });  
        return  JacksonUtil.readValue(result, valueType);
    }  
    @Override  
    public boolean expire(final String key, long expire) {  
        return redisTemplate.expire(key, expire, TimeUnit.SECONDS);  
    }  
  
    @Override  
    public <T> boolean setList(String key, List<T> list) {  
        String value = JacksonUtil.toJSon(list);  
        return set(key,value);  
    }  
  
    @Override  
    public <T> List<T> getList(String key,Class<T> clz) {  
        String json = get(key);  
        if(json!=null){  
            List<T> list = JacksonUtil.toList(json, clz);  
            return list;  
        }  
        return null;  
    }  
  
    @Override  
    public long lpush(final String key, Object obj) {  
        final String value = JacksonUtil.toJSon(obj);  
        long result = redisTemplate.execute(new RedisCallback<Long>() {  
            @Override  
            public Long doInRedis(RedisConnection connection) throws DataAccessException {  
                long count = connection.lPush(serializer.serialize(key), serializer.serialize(value));  
                return count;  
            }  
        });  
        return result;  
    }  
  
    @Override  
    public long rpush(final String key, Object obj) {  
        final String value = JacksonUtil.toJSon(obj);  
        long result = redisTemplate.execute(new RedisCallback<Long>() {  
            @Override  
            public Long doInRedis(RedisConnection connection) throws DataAccessException {  
                long count = connection.rPush(serializer.serialize(key), serializer.serialize(value));  
                return count;  
            }  
        });  
        return result;  
    }  
  
    @Override  
    public String lpop(final String key) {  
        String result = redisTemplate.execute(new RedisCallback<String>() {  
            @Override  
            public String doInRedis(RedisConnection connection) throws DataAccessException {  
                byte[] res =  connection.lPop(serializer.serialize(key));  
                return serializer.deserialize(res);  
            }  
        });  
        return result;  
    }

	@Override
	public String hGet(String key, String hashKey) {
		   String result = redisTemplate.execute(new RedisCallback<String>() {  
	            @Override  
	            public String doInRedis(RedisConnection connection) throws DataAccessException {  
	                byte[] res =  connection.hGet(serializer.serialize(key),serializer.serialize(hashKey));  
	                return serializer.deserialize(res);  
	            }  
	        });  
	        return result;  
	}

	@Override
	public Boolean hSet(String key, String hashKey, String obj) {
		Boolean result = redisTemplate.execute(new RedisCallback<Boolean>() {  
	            @Override  
	            public Boolean doInRedis(RedisConnection connection) throws DataAccessException {  
	    			 Boolean b=connection.hSet(serializer.serialize(key), serializer.serialize(hashKey), serializer.serialize(obj));
	    			 return b;
	            }  
	        });  
	        return result;  
	}  
	
	@Override
	public Boolean exists(String key) {
		Boolean result = redisTemplate.execute(new RedisCallback<Boolean>() {  
	            @Override  
	            public Boolean doInRedis(RedisConnection connection) throws DataAccessException {  
	            	 return connection.exists(serializer.serialize(key));
	            }  
	        });  
	        return result;  
	}  
}
